#include <iostream>
#include <sstream>
#include <ctime>
#include <cstdlib>
#include <math.h>
#include<algorithm>
#include "Game.h"
#include "DeepSearchPlayer.h"

using namespace std;

DeepSearchPlayer::CandidateCell::CandidateCell(int color, Board* board,
		Cell* cell, Board::State* state) :
		mColor(color), mBoard(board), mCell(cell), mState(state) {
}

DeepSearchPlayer::CandidateCell::~CandidateCell() {
	delete mBoard;
}

bool operator<(const DeepSearchPlayer::CandidateCell& riLeft,
		const DeepSearchPlayer::CandidateCell& riRight) {
	return riLeft.mState->getPoint(riLeft.mColor)
			> riRight.mState->getPoint(riLeft.mColor);
}

bool DeepSearchPlayer::CandidateCell::isWideMarginWon(int color) {
	return mState->isWideMarginWon(color);
}

string DeepSearchPlayer::CandidateCell::toString() {
	stringstream sb;
	sb << Stone::toString(mColor) << "(" << mCell->getX() << ","
			<< mCell->getY() << "):" << mState->getPoint(mColor);
	return sb.str();
}

DeepSearchPlayer::DeepSearchPlayer(string name, Board* mainBoard, int depth,
		int maxDepth) :
		Player(name), mDepth(0), mMaxDepth(0), mNoGiveUp(false), mMainBoard(
				NULL), mMind(MIND_NONE) {
	mDepth = depth;
	mMaxDepth = maxDepth;
	mMainBoard = mainBoard;
}

void DeepSearchPlayer::setBoard(Board* board) {
	Player::setBoard(board);
	if (mMainBoard == NULL) {
		mMainBoard = board;
	}
}

void DeepSearchPlayer::setNoGiveUp(bool noGiveUp) {
	mNoGiveUp = noGiveUp;
}

Cell* DeepSearchPlayer::next() {
	Cell* nextCell = NULL;

	if (!mNoGiveUp && mDepth > mMaxDepth) {
		//            new Throwable().printStackTrace();
		return Cell::GIVE_UP;
	}
	vector<Cell*> cells = *(mBoard->findPutableCells(mColor));
	if (cells.empty()) {
		return NULL;
	} else if (cells.size() == 1) {
		return cells[0];
	}

	vector<CandidateCell*> advantageCells;

	vector<Cell*>::iterator it = cells.begin();
	while (it != cells.end()) {
		Cell* cell = (*it);
		CandidateCell* candidateCell = candidate(cell);
		if (candidateCell != NULL) {
			if (candidateCell->isWideMarginWon(mColor)) {
				mMind = MIND_WINNER;
				nextCell = candidateCell->mCell;
				break;
			} else if (!candidateCell->isWideMarginWon(
					mColor == Stone::BLACK ? Stone::WHITE : Stone::BLACK)) {
				advantageCells.push_back(candidateCell);
			}
		}
		++it;
	}
	if (nextCell != NULL) {
		clear(advantageCells);
		return nextCell;
	}

	if (advantageCells.empty()) {
		//            if (mNoGiveUp) {
		//                return cells.get(0);
		//            } else {
		mMind = MIND_LOOSER;
		return Cell::GIVE_UP;
		//            }
	}
	sort(advantageCells.begin(), advantageCells.end()); // vector

	//        System.out.println(advantageCells);

	vector<CandidateCell*>::iterator candidateCellIt = advantageCells.begin();
	while (candidateCellIt != advantageCells.end()) {
		CandidateCell* candidateCell = (*candidateCellIt);
		candidateCell = search(candidateCell);
		if (candidateCell != NULL) {
			nextCell = candidateCell->mCell;
			break;
		}
		++candidateCellIt;
	}

	if (nextCell == NULL) {
		nextCell = advantageCells[0]->mCell;
	}
	clear(advantageCells);
	return nextCell;
}

DeepSearchPlayer::CandidateCell* DeepSearchPlayer::candidate(Cell* cell) {
	Board* board = new Board(*mBoard);
	board->setStone(cell->getX(), cell->getY(), mColor);
	Board::State* state = board->getState();
	//        if (state.getPoint(mColor) >= 0) {
	return new CandidateCell(mColor, board, cell, state);
	//        } else {
	//            return NULL;
	//        }
}

DeepSearchPlayer::CandidateCell* DeepSearchPlayer::search(
		CandidateCell* candidateCell) {
	//        player1.setNoGiveUp(true);
	//        player2.setNoGiveUp(true);

	Board* board = candidateCell->mBoard;
	Cell* cell = candidateCell->mCell;
	int depth = (int) ceil(
			(double) MAX_DEPTH
					* ((double) mMainBoard->getStoneCount()
							/ (BOARD_SIZE * BOARD_SIZE)));
	int emptys = mMainBoard->getEmptyCellCount();
	if (emptys <= 24) {
		depth = 100;
		depth = 3;
	} else if (emptys <= 32) {
		depth = 7;
		depth = 3;
	} else if (emptys <= 40) {
		depth = 5;
	} else if (emptys <= 44) {
		depth = 4;
	} else if (emptys <= 48) {
		depth = 3;
	} else {
		depth = 3;
	}
		depth = 3;
	DeepSearchPlayer player1("one", mMainBoard, mDepth + 1, depth);
	DeepSearchPlayer player2("two", mMainBoard, mDepth + 1, depth);
	//        System.out.println("main board : " + mMainBoard.getEmptyCellCount());
	//        if (mMainBoard.getEmptyCellCount() < 24) {
	//            player1.setNoGiveUp(true);
	//            player2.setNoGiveUp(true);
	//        }

	Game game(&player1, &player2, board);
	game.start();
	Board::State* state = game.getState();
	//        return new CandidateCell(mColor, board, cell, state);
	if (player1.hearMind() != MIND_LOOSER) {
		mMind = player1.hearMind();
		return new CandidateCell(mColor, board, cell, state);
	} else {
		return NULL;
	}
}

void DeepSearchPlayer::clear(vector<CandidateCell*> cells) {
//	vector<CandidateCell*>::iterator it = cells.begin();
//	while (it != cells.end()) {
//		CandidateCell* cell = (*it);
//		delete cell;
//		++it;
//	}
}

int DeepSearchPlayer::hearMind() {
	return mMind;
}
//}
